#ifndef __PROCESS_H_
#define __PROCESS_H_

#include <arch/interrupts.h> 
#include <fs.h>
#include <ds/mutex.h>
#include <ds/waitq.h>

#define MAX_PROCESS 64
#define TIME_SLICE 50

#define FORK_PROCESS 0
#define FORK_KTHREAD 1
#define FORK_THREAD  2

typedef enum {
    PROCESS_UNUSED,
    PROCESS_RUNNING,
    PROCESS_WAITING,
    PROCESS_SLEEPING,
    PROCESS_BLOCKING,
    PROCESS_READY,
    PROCESS_DEAD
} process_state;

struct process;

struct mm {
    struct process* proc;
    uptr code_start, code_end;
    uptr data_start, data_end;
    uptr heap_start, heap_end;
    uptr ustack_top, ustack_bottom;
    atomic_int ref_count;
    mutex_t lock;
    u32 vma_count;
    u32 page_count;
    struct vma* vma_list;
};

// this struct layout will affect the switch_to function
struct process {
    /* switch_to related layout */
    pid_t pid;
    uptr ustack_top;
    uptr cr3;
    isr_param context;
    /* switch_to related layout */
    struct mm* mm;
    process_state state;
    struct process* parent;
    lnode_t threads;
    dentry_t* cwd;
    fd_table_t* fd_table;
    lnode_t waitq;
    s32 k_status;
    s32 exit_code;
    u32 pgf_count;
};

extern volatile struct process* cur_proc;

void process_init();

int kthread_create(void (*func)(void*), void* arg);

void assign_return_context(u32 return_to_kernel, struct process* p, uptr kstk_top);

struct mm* mm_alloc(struct process* proc);

void mm_free(struct mm* mm);

#endif // __PROCESS_H_